package com.madou.dbtool.redis.terminal;

import com.madou.common.annotation.HideClass;
import com.madou.dbtool.language.enums.ContentTypeEnum;
import com.madou.dbtool.redis.manager.RedisSourceManager;
import com.madou.dbtool.redis.utils.BytesToStringUtil;
import com.madou.dbtool.ui.table.skin.MTableSkin;
import com.madou.dbtool.ui.terminal.editor.TerminalEditorPanel;
import com.madou.dbtool.ui.terminal.style.TerminalSkin;
import redis.clients.jedis.GeoCoordinate;
import redis.clients.jedis.resps.*;

import javax.swing.*;
import javax.swing.text.Element;
import java.awt.*;
import java.awt.event.KeyAdapter;
import java.awt.event.KeyEvent;
import java.awt.event.MouseAdapter;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;
import java.util.Map;

/**
 * @author miukoo
 * Redis命令行客户端
 */
@HideClass
public abstract class RedisTerminal extends TerminalEditorPanel {

    // 资源管理器
    RedisSourceManager redisSourceManager;

    public RedisTerminal(ContentTypeEnum contentTypeEnum) {
        super(contentTypeEnum);
    }

    // 获取数据库的索引
    public abstract int getDBIndex();
    /**
     * 执行命令
     * @param commandText
     * @return
     */
    @Override
    public List<String> execute(String commandText) {
        List<String> result = new ArrayList<>();
        try {
            commandText  = commandText.replaceAll("\\s+", " ");
            Object object = redisSourceManager.execute(getDBIndex(), commandText);
            paintObject(object, result);
        }catch (Exception e){
            result.add(e.getMessage());
        }
        return result;
    }


    /**
     * 输出返回类型
     * @param object
     * @param result
     */
    public void paintObject(Object object,List<String> result){
        if(object instanceof Collection){
            Collection sets = (Collection)object;
            for (Object set : sets) {
                paintObject(set,result);
            }
        }else if(object instanceof byte[]){
            paintObject(BytesToStringUtil.byte2Hex((byte[])object),result);
        }else if(object instanceof Tuple){
            Tuple tuple = (Tuple)object;
            String temp = String.format("[score:%s] %s",tuple.getScore(),tuple.getElement());
            result.add(temp);
        }else if(object instanceof Map){
            Map maps = (Map)object;
            for (Object key : maps.keySet()) {
                paintObject(key,result);
                result.add("  =  ");
                Object value = maps.get(key);
                paintObject(value,result);
            }
        }else if(object instanceof Map.Entry){
            Map.Entry maps = ( Map.Entry)object;
            paintObject(maps.getKey(),result);
            result.add("  =  ");
            paintObject(maps.getValue(),result);
        }else if(object instanceof LCSMatchResult){
            LCSMatchResult lcs = (LCSMatchResult)object;
            result.add(lcs.toString());
        }else if(object instanceof AccessControlUser){
            AccessControlUser acc = (AccessControlUser)object;
            result.add(acc.toString());
        }else if(object instanceof GeoRadiusResponse){
            GeoRadiusResponse grr = (GeoRadiusResponse)object;
            String temp = String.format("[coordinate:%s] [member:%s] [distance:%d] [rawScore:%d]",grr.getCoordinate().toString(),new String(grr.getMember()),grr.getDistance(),grr.getRawScore());
            result.add(temp);
        }else if(object instanceof GeoCoordinate){
            GeoCoordinate acc = (GeoCoordinate)object;
            result.add(acc.toString());
        }else if(object instanceof ScanResult){
            ScanResult scan = (ScanResult)object;
            result.add(scan.getCursor());
            for (Object key : scan.getResult()) {
                paintObject(key,result);
            }
        }else{
            if(object!=null) {
                String[] temp = object.toString().split("\n");
                for (int i = 0; i < temp.length; i++) {
                    result.add(temp[i]);
                }
            }else{
                result.add("null");
            }
        }
    }

    public void setRedisSourceManager(RedisSourceManager redisSourceManager) {
        this.redisSourceManager = redisSourceManager;
    }

    public RedisSourceManager getRedisSourceManager() {
        return redisSourceManager;
    }
}
